package main

import (
	"container/list"
	"fmt"
)

func main() {
	// 列表使用 container/list 包来实现，内部的实现原理是双链表，列表能够高效地进行任意位置的元素插入和删除操作
	// list 的初始化有两种方法：分别是使用 New() 函数和 var 关键字声明，两种方法的初始化效果都是一致的。
	// 通过 container/list 包的 New() 函数初始化 list变量名 := list.New()
	// 通过 var 关键字声明初始化 listvar 变量名 list.List
	// 列表与切片和 map 不同的是，列表并没有具体元素类型的限制，因此，列表的元素可以是任意类型，这既带来了便利，也引来一些问题，例如给列表中放入了一个 interface{} 类型的值，取出值后，如果要将 interface{} 转换为其他类型将会发生宕机

	// 小助手：把链表内容打印成一行

	l := list.New()

	// 1. 尾部插入
	l.PushBack("canon")
	printList(l) // canon

	// 2. 头部插入
	l.PushFront(67)
	printList(l) // 67 canon

	// 3. 再尾部插入，拿到 *list.Element
	element := l.PushBack("fist")
	printList(l) // 67 canon fist

	// 4. 在 element 后面插
	l.InsertAfter("high", element)
	printList(l) // 67 canon fist high

	// 5. 在 element 前面插
	l.InsertBefore("noon", element)
	printList(l) // 67 canon noon fist high

	// 6. 删除 element（fist）
	l.Remove(element)
	printList(l) // 67 canon noon high

	// 7. 批量把另一个链表整体拼到头部
	other := list.New()
	other.PushBack("A")
	other.PushBack("B")
	l.PushFrontList(other)
	printList(l) // A B 67 canon noon high
	printListReverse(l)
}
// 从前往后遍历打印链表内容
func printList(l *list.List) {
	for e := l.Front(); e != nil; e = e.Next() {
		fmt.Printf("%v ", e.Value)
	}
	fmt.Println()
}
// 从后往前遍历
func printListReverse(l *list.List) {
	for e := l.Back(); e != nil; e = e.Prev() {
		fmt.Printf("%v ", e.Value)
	}
	fmt.Println()
}